#include "client.h"
#include "client_util.h"
#include <crypt.h>
#include <termios.h>//加上这个头文件


void remove_newlines(char *str) {
    int len = strlen(str);                                    
    if (len > 0 && str[len - 1] == '\n') {                       
        str[len - 1] = '\0';                                     
    }                                                                  
}

void disable_echo() {
    struct termios tty;
    tcgetattr(STDIN_FILENO, &tty);
    tty.c_lflag &= ~ECHO;
    tcsetattr(STDIN_FILENO, TCSANOW, &tty);
}

void enable_echo() {
    struct termios tty;
    tcgetattr(STDIN_FILENO, &tty);
    tty.c_lflag |= ECHO;
    tcsetattr(STDIN_FILENO, TCSANOW, &tty);
}

int tcpConnect(const char* ip, unsigned short port) {
    //1. 创建TCP的客户端套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd < 0) {
        perror("socket");
        return -1;
    }

    //2. 指定服务器的网络地址
    struct sockaddr_in serveraddr;
    //初始化操作,防止内部有脏数据
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;//指定IPv4
    serveraddr.sin_port = htons(port);//指定端口号
                                      //指定IP地址
    serveraddr.sin_addr.s_addr = inet_addr(ip);

    //3. 发起建立连接的请求
    int ret = connect(sockfd, (const struct sockaddr*)&serveraddr, sizeof(serveraddr));
    if(ret < 0) {
        perror("connect");
        close(sockfd);
        return -1;
    }

    return sockfd;
}

void userLogin(int clientfd) {
    train_t train;
    userLoginOne(clientfd, &train);

    // 用户名存在才进行第二步密码验证
    if (train.type == LOGIN_STEP_ONE_OK) {
        userLoginTwo(clientfd, &train);
    }
}
void userLoginOne(int clientfd, train_t *train) {
    while (1) {
        memset(train, 0, sizeof(train_t));                               
        printf("please enter user name: ");                                
        fflush(stdout);                                                 
        char user_name[20] = { 0 };                                                
        if (fgets(user_name, sizeof(user_name), stdin) == NULL) {          
            fprintf(stderr, "fgets false\n");                              
        }                                                                  

        // 清楚换行符                                                      
        int len = strlen(user_name);                                    
        if (len > 0 && user_name[len - 1] == '\n') {                       
            user_name[len - 1] = '\0';                                     
        }                                                                  

        train->len = len;                                                   
        train->type = LOGIN_STEP_ONE;                                       
        memcpy(train->buff, user_name, train->len);                          
        // 客户端把用户名发送过去                                          
        sendn(clientfd, train, sizeof(int) + sizeof(int) + train->len);    

        memset(train, 0, sizeof(train_t));
        recvn(clientfd, &train->len, sizeof(int));
        recvn(clientfd, &train->type, sizeof(int));

        if (train->type == LOGIN_STEP_ONE_ERR) {
            printf("username does not exist\n\n");
            userRegister(clientfd);
            return;
        }
        if (train->type == LOGIN_STEP_ONE_OK) {
            recvn(clientfd, train->buff, train->len);
            return;// 进入登录的第二个阶段
        }

    }

}
void userLoginTwo(int clientfd, train_t *train) {

    // 这里temp的buff中保留的就是发过来的setting
    train_t temp = *train;  
    while (1) {

        printf("please enter user password: ");
        fflush(stdout);

        disable_echo();//隐藏标准输入流在终端的显示
        char user_password[20] = { 0 };
        if (fgets(user_password, sizeof(user_password), stdin) == NULL) {
            fprintf(stderr, "fgets false\n");
        }
        // 清楚换行符
        int len = strlen(user_password);
        if (len > 0 && user_password[len - 1] == '\n') {
            user_password[len - 1] = '\0';
        }
        enable_echo();//取消隐藏标准输入流在终端的显示

        // 客户端发送密文给服务端，这里的crypt_r是线程安全的
        struct crypt_data data;
        memset(&data, 0, sizeof(data));
        char *encrypted = crypt_r(user_password, temp.buff, &data);
        if (encrypted == NULL) {
            fprintf(stderr, "encrypted false\n");
            exit(-1);
        }

        memset(train, 0, sizeof(train_t));
        train->len = strlen(data.output);
        train->type = LOGIN_STEP_TWO;
        memcpy(train->buff, data.output, train->len);

        // 发送密文过去
        sendn(clientfd, train, sizeof(int) + sizeof(int) + train->len);

        memset(train, 0, sizeof(train_t));
        recvn(clientfd, &train->len, sizeof(int));
        recvn(clientfd, &train->type, sizeof(int));

        printf("\n");
        if (train->type == LOGIN_STEP_TWO_ERR) {
            printf("wrong password\n\n");
            //continue;
            //密码输错,直接程序退出 by sjk 2024.6.20
            exit(0);
        }
        if (train->type == LOGIN_STEP_TWO_OK) {
            printf("login successful\n\n");

            // 接受服务端传递过来的信息，打印bash
            curr_info_t curr;
            recvn(clientfd, &curr, sizeof(curr));
            currinfo_printf(curr);

            return ;
        }

    }

}

void userRegister(int clientfd) {
    train_t train;
    printf("register or not (yes / no) : ");
    fflush(stdout);
    char register_flag[20];
    if (fgets(register_flag, sizeof(register_flag), stdin) == NULL) {
        printf("input is illegal\n\n");
        exit(-1);
    }
    int len = strlen(register_flag);
    if (len > 0 && register_flag[len - 1] == '\n') {
        register_flag[len - 1] = '\0';
    }

    // 进行登录
    if (strcmp(register_flag, "yes") == 0  || strcmp(register_flag, "YES") == 0
        || strcmp(register_flag, "y") == 0 || strcmp(register_flag, "Y") == 0) {
        userRegisterOne(clientfd, &train);  
        userRegisterTwo(clientfd, &train);
    }
    else {
        exit(-1);
    }

}
void userRegisterOne(int clientfd, train_t *train) {

    // 因为时用户名不存在，走到这一步的，所以，注册的第一个阶段时一定成功的
    printf("please enter the new username to register: ");
    fflush(stdout);
    char user_name[20];
    if (fgets(user_name, sizeof(user_name), stdin) == NULL) {
        printf("input is illegal\n\n");
        exit(-1);
    }
    remove_newlines(user_name);

    memset(train, 0, sizeof(train_t));
    train->len = strlen(user_name);
    train->type = REGISTER_STEP_ONE;
    memcpy(train->buff, user_name, train->len);

    // 发送新注册的用户名给服务端
    sendn(clientfd, train, sizeof(int) + sizeof(int) + train->len);

    memset(train, 0, sizeof(train_t));
    recvn(clientfd, &train->len, sizeof(int));
    recvn(clientfd, &train->type, sizeof(int));

    if (train->type == REGISTER_STEP_ONE_ERR) {
        // 注册失败，直接退出
        printf("user exists, registration failed\n\n");
        exit(-1);
    }
    recvn(clientfd, train->buff, train->len);
    // 进入第二阶段
}
void userRegisterTwo(int clientfd, train_t *train) {

    // 这里temp的buff中保留的就是发过来的setting
    train_t temp = *train;  
    while (1) {
        char user_password1[20] = { 0 };
        char user_password2[20] = { 0 };

        printf("please enter user password: ");
        fflush(stdout);

        disable_echo();//隐藏标准输入流在终端的显示
        if (fgets(user_password1, sizeof(user_password1), stdin) == NULL) {
            fprintf(stderr, "fgets false\n");
        }
        // 清楚换行符
        int len = strlen(user_password1);
        if (len > 0 && user_password1[len - 1] == '\n') {
            user_password1[len - 1] = '\0';
        }

        printf("\nplease enter user password again: ");
        fflush(stdout);

        if (fgets(user_password2, sizeof(user_password2), stdin) == NULL) {
            fprintf(stderr, "fgets false\n");
        }
        // 清楚换行符
        len = strlen(user_password2);
        if (len > 0 && user_password2[len - 1] == '\n') {
            user_password2[len - 1] = '\0';
        }

        enable_echo();//取消隐藏标准输入流在终端的显示

        if (strcmp(user_password1, user_password2) != 0) {
            printf("\ntwo passwords are inconsistentn\n\n");
            continue;
        }
        // 客户端发送密文给服务端，这里的crypt_r是线程安全的
        struct crypt_data data;
        memset(&data, 0, sizeof(data));
        char *encrypted = crypt_r(user_password1, temp.buff, &data);
        if (encrypted == NULL) {
            fprintf(stderr, "encrypted false\n");
            exit(-1);
        }

        memset(train, 0, sizeof(train_t));
        train->len = strlen(data.output);
        train->type = REGISTER_STEP_TWO;
        memcpy(train->buff, data.output, train->len);

        // 发送密文过去
        sendn(clientfd, train, sizeof(int) + sizeof(int) + train->len);
        printf("\nregistration success\n\n");

        userLogin(clientfd);
        return ;
    }
} 


